package com.enjoyor.soa.traffic.util.helper;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import com.vividsolutions.jts.io.WKTWriter;
import com.vividsolutions.jts.operation.buffer.BufferOp;
import oracle.spatial.geometry.JGeometry;
import oracle.spatial.util.GeometryExceptionWithContext;
import oracle.spatial.util.WKT;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.grid.Grids;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;

import java.io.StringWriter;
import java.util.*;

/**
 * @author HGD
 * @version V1.0
 * @Title: GeoToolsHelper.java
 * @Package com.enjoyor.soa.traffic.util.helper
 * @Description: (用一句话描述该文件做什么)
 * @email huguangda@enjoyor.net
 * @date 2017年12月5日 上午9:12:12
 */
public class GeoToolsHelper {
    private final static double M_PI = Math.PI;
    private final static double EARTH_RADIUS = 6378137.0;//地球半径

    public static String Geometry2WKT(Geometry geom) {
        WKTWriter wkt = new WKTWriter();
        String wktString = wkt.write(geom);
        return wktString;
    }

    public static Geometry WKT2Geometry(String wktStr) {
        WKTReader reader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
        Geometry geom = null;
        try {
            geom = reader.read(wktStr);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return geom;
    }

    /**
     * @param geom
     * @return
     * @throws
     * @Title: JGeometry2WKT
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public static String JGeometry2WKT(JGeometry geom) {
        String wktStr = null;
        try {
            WKT wkt = new WKT();
            wktStr = new String(wkt.fromJGeometry(geom));
            return wktStr;
        } catch (GeometryExceptionWithContext e) {
            e.printStackTrace();
        }
        return wktStr;
    }

    /**
     * @param wktstr
     * @return
     * @throws
     * @Title: WKTJGeometry
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public static JGeometry WKTJGeometry(String wktstr) {
        JGeometry geom = null;
        try {
            WKT wkt = new WKT();
            geom = wkt.toJGeometry(wktstr.getBytes());
            return geom;
        } catch (GeometryExceptionWithContext e) {
            e.printStackTrace();
        }
        return geom;
    }

    /**
     * wkt格式转换成arcgis js api 通用图形字符串格式 @Title: Wkt2ArcJson @Description:
     * TODO(这里用一句话描述这个方法的作用) @param wkt @return @throws
     */
    public static String Wkt2ArcJson(String wkt) {
        StringBuffer tempStr = new StringBuffer("");
        wkt = wkt.trim();
        if (wkt.startsWith("POINT")) {
            int s = wkt.indexOf("POINT (");
            int e = wkt.indexOf(")");
            String coordsString = wkt.substring(s + 7, e);
            String[] coords;
            coords = coordsString.trim().split(" ");
            tempStr.append("{");
            tempStr.append("\"x\":");
            tempStr.append(coords[0] + ",");
            tempStr.append("\"y\":");
            tempStr.append(coords[1] + ",");
            tempStr.append("\"spatialReference\":{\"wkid\":4326}}");
        } else if (wkt.startsWith("LINESTRING")) {
            int s = wkt.indexOf("LINESTRING (");
            int e = wkt.indexOf(")");
            String coordsString = wkt.substring(s + 12, e);
            String[] coords;
            coords = coordsString.split(",");
            tempStr.append("{\"paths\":[[");
            for (int j = 0; j < coords.length; j++) {
                String[] xy = coords[j].trim().split(" ");
                tempStr.append("[");
                tempStr.append(String.valueOf(xy[0]) + ",");
                tempStr.append(String.valueOf(xy[1]) + "]");
                if (j < coords.length - 1) {
                    tempStr.append(",");
                }
            }
            tempStr.append("]]");
            tempStr.append(",\"spatialReference\":{\"wkid\":4326}}");
        } else if (wkt.startsWith("POLYGON")) {

            int s = wkt.indexOf("POLYGON ((");
            int e = wkt.indexOf("))");
            String coordsString = wkt.substring(s + 10, e);
            String[] coords;
            coords = coordsString.split(",");
            tempStr.append("{\"rings\":[[");
            for (int j = 0; j < coords.length; j++) {
                String[] xy = coords[j].trim().split(" ");
                tempStr.append("[");
                tempStr.append(String.valueOf(xy[0]) + ",");
                tempStr.append(String.valueOf(xy[1]) + "]");
                if (j < coords.length - 1) {
                    tempStr.append(",");
                }
            }
            tempStr.append("]]");
            tempStr.append(",\"spatialReference\":{\"wkid\":4326}}");
        }
        return tempStr.toString();
    }

    /**
     * arcgis js api 通用js字符串转换成wkt格式字符串 @Title: ArcJson2Wkt @Description:
     * TODO(这里用一句话描述这个方法的作用) @param jsonText @return @throws
     */
    public static String ArcJson2Wkt(String jsonText) {
        JSONObject geomjson = JSONObject.parseObject(jsonText);
        StringBuffer tempStr = new StringBuffer("");
        if (geomjson.get("rings") != null) {
            JSONArray rings = (JSONArray) geomjson.get("rings");
            List ring = (List) rings.get(0);
            tempStr.append("POLYGON((");
            for (int j = 0; j < ring.size(); j++) {
                List r = (List) ring.get(j);
                String x = r.get(0).toString();
                String y = r.get(1).toString();
                tempStr.append(x);
                tempStr.append(" ");
                tempStr.append(y);
                if (j < ring.size() - 1) {
                    tempStr.append(",");
                }
            }
            tempStr.append("))");
        } else if (geomjson.get("x") != null) {
            tempStr.append("POINT(");
            String x = geomjson.get("x").toString();
            String y = geomjson.get("y").toString();
            tempStr.append(x);
            tempStr.append(" ");
            tempStr.append(y);
            tempStr.append(")");
        } else if (geomjson.get("paths") != null) {
            JSONArray paths = (JSONArray) geomjson.get("paths");
            List path = (List) paths.get(0);
            tempStr.append("LINESTRING(");
            for (int j = 0; j < path.size(); j++) {
                List r = (List) path.get(j);
                String x = r.get(0).toString();
                String y = r.get(1).toString();
                tempStr.append(x);
                tempStr.append(" ");
                tempStr.append(y);
                if (j < path.size() - 1) {
                    tempStr.append(",");
                }
            }
            tempStr.append(")");
        }
        return tempStr.toString();
    }

    /**
     * 度转弧度
     *
     * @param d
     * @return
     * @throws
     * @Title: rad
     * @Description: TODO(获取弧度)
     */
    private static double rad(double d) {
        return d * M_PI / 180.0;
    }

    /**
     * 转换长度单位，从经纬度到米 @Title: degree2meter @Description:
     * TODO(这里用一句话描述这个方法的作用) @param meter @return @throws
     */
    public static double degree2meter(double meter) {
        double degree = meter / (2 * M_PI * EARTH_RADIUS) * 360;
        return degree;
    }

    /**
     * 判断量图形是否包含关系 @Title: GeomContains @Description:
     * TODO(这里用一句话描述这个方法的作用) @param containGeomArcjson @param
     * becontainGeomArcjson @return @throws ParseException @throws
     * GeometryExceptionWithContext @throws
     */
    public static boolean GeomContains(String containGeomArcjson, String becontainGeomArcjson)
            throws ParseException, GeometryExceptionWithContext {
        String wktString1 = ArcJson2Wkt(becontainGeomArcjson);
        String wktString2 = ArcJson2Wkt(containGeomArcjson);
        Geometry g1 = WKT2Geometry(wktString1);
        Geometry g2 = WKT2Geometry(wktString2);
        return g2.contains(g1);

    }

    public static boolean GeomContains(String containGeomArcjson, double x, double y)
            throws ParseException, GeometryExceptionWithContext {
        String wktString1 = "POINT(" + Double.toString(x) + " " + Double.toString(y) + ")";
        String wktString2 = ArcJson2Wkt(containGeomArcjson);
        Geometry g1 = WKT2Geometry(wktString1);
        Geometry g2 = WKT2Geometry(wktString2);
        return g2.contains(g1);

    }

    /**
     * 对containGeomArcjson图形进行缓冲操作后再判断与becontainGeomArcjson图形的包含关系，是否包含 @Title:
     * BufferGeomContains @Description: TODO(这里用一句话描述这个方法的作用) @param
     * containGeomArcjson @param becontainGeomArcjson @param
     * distance @return @throws ParseException @throws
     * GeometryExceptionWithContext @throws
     */
    public static boolean BufferGeomContains(String containGeomArcjson, String becontainGeomArcjson, double distance)
            throws ParseException, GeometryExceptionWithContext {
        distance = degree2meter(distance);
        String polygonwktString = ArcJson2Wkt(containGeomArcjson);
        String pointwktString = ArcJson2Wkt(becontainGeomArcjson);
        Geometry gpoint = WKT2Geometry(pointwktString);
        Geometry gpoly = WKT2Geometry(polygonwktString);
        Geometry bufferPoly = Buffer(gpoly, distance);
        return bufferPoly.contains(gpoint);

    }

    /**
     * 对图形geom缓冲distance距离，返回缓冲后的面对象 @Title: Buffer @Description:
     * TODO(这里用一句话描述这个方法的作用) @param geom @param distance @return @throws
     * ParseException @throws
     */
    public static Geometry Buffer(Geometry geom, double distance) throws ParseException {
        distance = degree2meter(distance);
        BufferOp bufOp = new BufferOp(geom);
        bufOp.setEndCapStyle(BufferOp.CAP_BUTT);
        Geometry bg = bufOp.getResultGeometry(distance);
        return bg;
    }

    /**
     * 对arcgisjson字符串进行转换，并返回缓冲后的面对象，以arcgijson字符串方式返回 @Title:
     * buffer @Description: TODO(这里用一句话描述这个方法的作用) @param arcgisJsonGeom @param
     * distance @return @throws ParseException @throws
     */
    public static String buffer(String arcgisJsonGeom, double distance) throws ParseException {
        distance = degree2meter(distance);
        String geomwkt = ArcJson2Wkt(arcgisJsonGeom);
        Geometry gpoint = WKT2Geometry(geomwkt);
        BufferOp bufOp = new BufferOp(gpoint);
        bufOp.setEndCapStyle(BufferOp.CAP_ROUND);
        Geometry bg = bufOp.getResultGeometry(distance);
        String wktString = Geometry2WKT(bg);
        String arcJson = Wkt2ArcJson(wktString);
        return arcJson;
    }

    /**
     * 判断两条线是否有焦点，并返回焦点坐标
     *
     * @param arcgisJsonGeom1
     * @param arcgisJsonGeom2
     * @return
     * @throws ParseException
     * @throws
     * @Title: intersectsGeo
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public static Map<String, Object> intersectsGeo(String arcgisJsonGeom1, String arcgisJsonGeom2) throws ParseException {
        String geomwkt1 = ArcJson2Wkt(arcgisJsonGeom1);
        String geomwkt2 = ArcJson2Wkt(arcgisJsonGeom2);
        LineString geometry1 = (LineString) WKT2Geometry(geomwkt1);
        LineString geometry2 = (LineString) WKT2Geometry(geomwkt2);
        Geometry interPoint = geometry1.intersection(geometry2);//相交点
        Map<String, Object> map = new HashMap<>();
        map.put("intersects", geometry1.intersects(geometry2));
        map.put("Coordinates", interPoint.getCoordinates());
        //System.out.println(interPoint.toText()); 
        return map;
    }

    /**
     * 获取线对象上的随机一点
     *
     * @param lines
     * @return
     * @throws
     * @Title: getGetRandomLine
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public static String getGetRandomLine(Geometry lines) {
        Coordinate[] cs = lines.getCoordinates();
        int index = (int) (0 + Math.random() * ((cs.length - 2) - 0 + 1));
        String pointwkt = getGetRandomPoints(cs[index].x, cs[index].y, cs[index + 1].x, cs[index + 1].y);
        return pointwkt;
    }

    /**
     * 获取arcgisjson字符串对象上的一个随机点
     *
     * @param linesstr
     * @return
     * @throws
     * @Title: getGetRandomLine
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public static String getGetRandomLine(String linesstr) {
        String wkt = ArcJson2Wkt(linesstr);
        Geometry lines;
        String pointwkt = "";
        lines = WKT2Geometry(wkt);
        Coordinate[] cs = lines.getCoordinates();
        int index = (int) (0 + Math.random() * ((cs.length - 2) - 0 + 1));
        pointwkt = getGetRandomPoints(cs[index].x, cs[index].y, cs[index + 1].x, cs[index + 1].y);
        return pointwkt;
    }

    /**
     * 获取线段上一个随机点
     *
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @return
     * @throws
     * @Title: getGetRandomPoints
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    public static String getGetRandomPoints(double x1, double y1, double x2, double y2) {
        if (x1 == x2) {
            int dy = (int) ((y1 + Math.random() * (y2 - y1)) * 10000);
            double ty = (double) dy / 10000;
            return "POINT(" + x1 + " " + ty + ")";
        } else {
            double k = (y2 - y1) / (x2 - x1);
            double b = y1 - k * x1;
            int dx = (int) ((x1 + Math.random() * (x2 - x1)) * 10000);
            double tx = (double) dx / 10000;
            int dy = (int) ((tx * k + b) * 10000);
            double ty = (double) dy / 10000;
            return "POINT(" + tx + " " + ty + ")";
        }
    }
/*	private double[] LinearEquationXY(JGeometry geom,int count)
	{
		geom.getSize();
		double length=geom.getLength();
		double m=length/count;
 
		
		double L = m / (2 * M_PI * EARTH_RADIUS) * 360;
		double x= (ex-bx)*L/Math.sqrt((ey-by)*(ey-by)+(ex-bx)*(ex-bx))+bx; 
		double y= (ey-by)*L/Math.sqrt((ey-by)*(ey-by)+(ex-bx)*(ex-bx))+by;
		return  new double[]{x,y};
	}*/

    /**
     * 获取线段的角度
     *
     * @param px1
     * @param py1
     * @param px2
     * @param py2
     * @return
     * @throws
     * @Title: getAngle
     * @Description: TODO(获取线段的角度)
     */
    private static double getAngle(double px1, double py1, double px2, double py2) {
        // 两点的x、y值
        double x = px2 - px1;
        double y = py2 - py1;
        double hypotenuse = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        if (hypotenuse == 0.0) return 0.0;
        // 斜边长度
        double cos = x / hypotenuse;
        double radian = Math.acos(cos);
        // 求出弧度
        double angle = 180 / (M_PI / radian);
        // 用弧度算出角度
        if (y < 0) {
            angle = -angle;
        } else if ((y == 0) && (x < 0)) {
            angle = 180;
        }
        return angle;
    }

    /**
     * 计算两点间距离
     *
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return
     * @throws
     * @Title: GetPointDistance
     * @Description: TODO(计算两点间距离)
     */
    public static double GetPointDistance(double lng1, double lat1, double lng2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 100000);
        double s1 = s / 100000;
        return s1;
    }

    /**
     * 求 cy 可以根据d / a到b距离 = a到c垂直距离 / a 到 b的垂直距离。
     *
     * @param bx
     * @param by
     * @param ex
     * @param ey
     * @param m
     * @return
     * @throws
     * @Title: LinearEquationX
     * @Description: TODO(获取线段上距离起点m米位置点的X坐标值)
     */
    private double LinearEquationX(double bx, double by, double ex, double ey, double m) {
        double L = m / (2 * M_PI * EARTH_RADIUS) * 360;
        return (ex - bx) * L / Math.sqrt((ey - by) * (ey - by) + (ex - bx) * (ex - bx)) + bx;
    }

    /**
     * 求 cy 可以根据d / a到b距离 = a到c垂直距离 / a 到 b的垂直距离。
     *
     * @param bx
     * @param by
     * @param ex
     * @param ey
     * @param m
     * @return
     * @throws
     * @Title: LinearEquationY
     * @Description: TODO(获取线段上距离起点m米位置点的Y坐标值)
     */
    private double LinearEquationY(double bx, double by, double ex, double ey, double m) {
        double L = m / (2 * M_PI * EARTH_RADIUS) * 360;
        return (ey - by) * L / Math.sqrt((ey - by) * (ey - by) + (ex - bx) * (ex - bx)) + by;
    }

    /**
     * 求 cy 可以根据d / a到b距离 = a到c垂直距离 / a 到 b的垂直距离。
     *
     * @param bx
     * @param by
     * @param ex
     * @param ey
     * @param m
     * @return
     * @throws
     * @Title: LinearEquationY
     * @Description: TODO(获取线段上距离起点m米位置点的坐标值)
     */
    private static double[] LinearEquationXY(double bx, double by, double ex, double ey, double m) {
        double L = m / (2 * M_PI * EARTH_RADIUS) * 360;
        double x = (ex - bx) * L / Math.sqrt((ey - by) * (ey - by) + (ex - bx) * (ex - bx)) + bx;
        double y = (ey - by) * L / Math.sqrt((ey - by) * (ey - by) + (ex - bx) * (ex - bx)) + by;
        return new double[]{x, y};
    }

    /**
     * @param geom
     * @param m
     * @return
     * @throws
     * @Title: LinearEquationXY
     * @Description: TODO(获取折线上距离起点M米的坐标点)
     */
    public static double[] LinearEquationXY(JGeometry geom, double m) {
        double[] arrpaths = geom.getOrdinatesArray();//获取矢量对象的坐标数组
        double distanceBegin = 0.0;
        double[] result = null;
        for (int i = 0; i < arrpaths.length - 3; ) {//生成线段数组，用以对比点位距离
            double bx = arrpaths[i];
            double by = arrpaths[i + 1];
            double ex = arrpaths[i + 2];
            double ey = arrpaths[i + 3];
            double cd = GetPointDistance(bx, by, ex, ey);    //获取线段长度
            distanceBegin += cd;
            if (distanceBegin > m) {
                double beforeLength = distanceBegin - cd;
                double thisLength = m - beforeLength;
                result = LinearEquationXY(bx, by, ex, ey, thisLength);
                break;
            }
            i = i + 2;
        }
        return result;
    }

    /**
     * 获取点到线段上最近的距离
     *
     * @param PAx
     * @param PAy
     * @param PBx
     * @param PBy
     * @param P3x
     * @param P3y
     * @return 返回最近的点和距离
     * @throws
     * @Title: GetNearestDistance
     * @Description: TODO(这里用一句话描述这个方法的作用)
     */
    private static Map<String, Object> GetNearestDistance(double PAx, double PAy, double PBx, double PBy, double P3x, double P3y) {
        Map<String, Object> map = new HashMap<>();
        map.put("x", 0.0);
        map.put("y", 0.0);
        map.put("length", 0.0);
        // ----------图2--------------------
        double a, b, c;
        a = GetPointDistance(PBx, PBy, P3x, P3y);
        if (a <= 0.00001)
            return map;
        b = GetPointDistance(PAx, PAy, P3x, P3y);
        if (b <= 0.00001)
            return map;
        c = GetPointDistance(PAx, PAy, PBx, PBy);
        if (c <= 0.00001) {
            map.put("length", a);
            return map;// 如果PA和PB坐标相同，则退出函数，并返回距离
            // ------------------------------
        }
        if (a * a >= b * b + c * c)// --------图3--------
        {
            map.put("x", PAx);
            map.put("y", PAy);
            map.put("length", b);
            return map;
        }
        // return b; // 如果是钝角返回b
        // --------图4-------
        if (b * b >= a * a + c * c) {
            map.put("x", PBx);
            map.put("y", PBy);
            map.put("length", a);
            return map;
        }

        // 图1
        double l = (a + b + c) / 2; // 周长的一半
        double lc = l - c > 0 ? l - c : 0;
        double lb = l - b > 0 ? l - b : 0;
        double la = l - a > 0 ? l - a : 0;
        double s = Math.sqrt(l * la * lb * lc); // 海伦公式求面积，也可以用矢量求
        //double k = (PBy - PAy) / (PBx - PAx);// 斜率

        double[] midpoint = GetProjectivePoint(PAx, PAy, PBx, PBy, P3x, P3y);
        map.put("x", midpoint[0]);
        map.put("y", midpoint[1]);
        map.put("length", 2 * s / c);
        if (map.get("length").toString().equals("NaN")) {
            System.out.println("计算面积出错了！");
        }
        return map;
    }
    /**
     * @ brief 根据两点求出垂线过第三点的直线的交点 @ param pt1 直线上的第一个点 @ param pt2 直线上的第二个点 @ param
     * pt3 垂线上的点 @ return 返回点到直线的垂直交点坐标
     */
    /**
     * 根据两点求出垂线过第三点的直线的交点
     *
     * @param pt1x 直线上的第一个点
     * @param pt1y
     * @param pt2x 直线上的第二个点
     * @param pt2y
     * @param pt3x
     * @param pt3y 垂线上的点
     * @return
     * @throws
     * @Title: GetProjectivePoint
     * @Description: TODO(根据两点求出垂线过第三点的直线的交点)
     */
    private static double[] GetProjectivePoint(double pt1x, double pt1y, double pt2x, double pt2y, double pt3x, double pt3y) {
        double[] r = new double[2];
        if (pt1x - pt2x == 0) {//平行于y 斜率不存在
            r[0] = pt1x;
            r[1] = pt3y;
            return r;
        }
        if (pt1y - pt2y == 0) {//平行于x 斜率=0
            r[0] = pt3x;
            r[1] = pt1y;
            return r;
        }

        double A = (pt1y - pt2y) / (pt1x - pt2x);
        double B = (pt1y - A * pt1x);
        // / > 0 = ax +b -y; 对应垂线方程为 -x -ay + m = 0;(mm为系数)
        // / > A = a; B = b;
        double m = pt3x + A * pt3y;

        // / 求两直线交点坐标

        double x = (m - A * B) / (A * A + 1);
        double y = A * x + B;
        r[0] = x;
        r[1] = y;
        return r;
    }

    /**
     * @param geo 先对象
     * @param x   需要映射的点位坐标x
     * @param y   需要映射的点位坐标y
     * @return
     * @throws
     * @Title: ProjectionPoint
     * @Description: TODO(映射点位到线路上并返回映射坐标 ， 距离映射点距离 ， 已映射后的点距离线段起点的距离)
     */
    public static Map<String, Object> getProjectionPoint(JGeometry geo, double x, double y) {
        List<Map<String, Double>> arr_paths = new ArrayList<Map<String, Double>>();
        double[] arrpaths = geo.getOrdinatesArray();//获取矢量对象的坐标数组
        double distanceBegin = 0.0;
        double minlength = 0;// 点离开线的距离
        Map<String, Object> temp = new HashMap<>();
        for (int i = 0; i < arrpaths.length - 3; ) {//生成线段数组，用以对比点位距离
            double bx = arrpaths[i];
            double by = arrpaths[i + 1];
            double ex = arrpaths[i + 2];
            double ey = arrpaths[i + 3];
            double cd = GetPointDistance(bx, by, ex, ey);    //获取线段长度
            distanceBegin += cd;
            Map<String, Double> p = new HashMap<String, Double>();
            p.put("beginPointX", bx);
            p.put("beginPointY", by);
            p.put("endPointX", ex);
            p.put("endPointY", ey);
            p.put("lineLength", cd);
            p.put("distanceStartPointLength", distanceBegin);
            p.put("lineAngle", getAngle(bx, by, ex, ey));
            arr_paths.add(p);
            i = i + 2;
        }
        ///////////////////////////
        for (int i = 0; i < arr_paths.size(); i++) {// 遍历线路数组计算长度
            Map<String, Object> near = GetNearestDistance(arr_paths.get(i).get("beginPointX"),
                    arr_paths.get(i).get("beginPointY"), arr_paths.get(i).get("endPointX"),
                    arr_paths.get(i).get("endPointY"), x, y);
            if ((double) near.get("length") < minlength || i == 0) {// 对比点到线的距离，获取最近的映射点
                minlength = (double) near.get("length");
                temp.put("x", near.get("x"));
                temp.put("y", near.get("y"));
                temp.put("index", i);
                temp.put("shortestDis", minlength);
                double disLine = arr_paths.get(i).get("distanceStartPointLength");
                double lengLine = arr_paths.get(i).get("lineLength");
                double disThis = GetPointDistance(arr_paths.get(i).get("beginPointX"), arr_paths.get(i).get("beginPointY"), (double) near.get("x"), (double) near.get("y"));
                temp.put("distanceStartPointLength", disLine - lengLine + disThis);
            }
        }
        return temp;
    }

    /**
     * @param geo 先对象
     * @param x   需要映射的点位坐标x
     * @param y   需要映射的点位坐标y
     * @return
     * @throws
     * @Title: ProjectionPoint
     * @Description: TODO(映射点位到线路上每一段折线并返回映射坐标 ， 距离映射点距离 ， 已映射后的点距离线段起点的距离列表)
     */
    public static List<Map> getProjectionPointList(JGeometry geo, double x, double y) {
        List<Map<String, Double>> arr_paths = new ArrayList<Map<String, Double>>();
        double[] arrpaths = geo.getOrdinatesArray();//获取矢量对象的坐标数组
        double distanceBegin = 0.0;
        for (int i = 0; i < arrpaths.length - 3; ) {//生成线段数组，用以对比点位距离
            double bx = arrpaths[i];
            double by = arrpaths[i + 1];
            double ex = arrpaths[i + 2];
            double ey = arrpaths[i + 3];
            double cd = GetPointDistance(bx, by, ex, ey);    //获取线段长度
            distanceBegin += cd;
            Map<String, Double> p = new HashMap<String, Double>();
            p.put("beginPointX", bx);
            p.put("beginPointY", by);
            p.put("endPointX", ex);
            p.put("endPointY", ey);
            p.put("lineLength", cd);
            p.put("distanceStartPointLength", distanceBegin);
            p.put("lineAngle", getAngle(bx, by, ex, ey));
            arr_paths.add(p);
            i = i + 2;
        }
        ///////////////////////////
        List<Map> list = new ArrayList<>();
        for (int i = 0; i < arr_paths.size(); i++) {// 遍历线路数组计算长度
            double minlength = 0;// 点离开线的距离
            Map<String, Object> near = GetNearestDistance(arr_paths.get(i).get("beginPointX"),
                    arr_paths.get(i).get("beginPointY"), arr_paths.get(i).get("endPointX"),
                    arr_paths.get(i).get("endPointY"), x, y);
            Map<String, Object> temp = new HashMap<>();
            minlength = (double) near.get("length");
            if (Double.isNaN(minlength)) {
                System.out.println("");
            }
            temp.put("x", near.get("x"));
            temp.put("y", near.get("y"));
            temp.put("index", i);
            temp.put("shortestDis", minlength);
            double disLine = arr_paths.get(i).get("distanceStartPointLength");
            double lengLine = arr_paths.get(i).get("lineLength");
            double disThis = GetPointDistance(arr_paths.get(i).get("beginPointX"), arr_paths.get(i).get("beginPointY"), (double) near.get("x"), (double) near.get("y"));
            temp.put("distanceStartPointLength", disLine - lengLine + disThis);
            list.add(temp);
        }
        list.sort(new Comparator<Map>() {
            @Override
            public int compare(Map o1, Map o2) {
                //这里是根据ID来排序，所以它为空的要剔除掉

                if (o1.get("shortestDis") == null || o2.get("shortestDis") == null) return 1;

                //if(o1.get("shortestDis").toString().equals("NaN")||o2.get("shortestDis").toString().equals("NaN"))
                //return 1;

                double ol1 = Double.parseDouble(o1.get("shortestDis").toString());
                double ol2 = Double.parseDouble(o2.get("shortestDis").toString());

                return (int) (ol1 - ol2);//这是顺序
            }
        });
        return list;
    }

    /**
     * @param geo  原始线对象
     * @param geo1 子线段
     * @return
     * @throws
     * @Title: ProjectionPoint
     * @Description: TODO(根据geo1裁剪线路geo 并组合成新的线段)
     */
    public static Map<String, Object> buildNewLine(JGeometry geo, JGeometry geo1) {
        List<Map<String, Double>> arr_paths = new ArrayList<Map<String, Double>>();
        double[] arrpaths = geo.getOrdinatesArray();//获取矢量对象的坐标数组
        double distanceBegin = 0.0;
        for (int i = 0; i < arrpaths.length - 3; ) {//生成线段数组，用以对比点位距离
            double bx = arrpaths[i];
            double by = arrpaths[i + 1];
            double ex = arrpaths[i + 2];
            double ey = arrpaths[i + 3];
            double cd = GetPointDistance(bx, by, ex, ey);    //获取线段长度
            distanceBegin += cd;
            Map<String, Double> p = new HashMap<String, Double>();
            p.put("beginPointX", bx);
            p.put("beginPointY", by);
            p.put("endPointX", ex);
            p.put("endPointY", ey);
            p.put("lineLength", cd);
            p.put("distanceStartPointLength", distanceBegin);
            p.put("lineAngle", getAngle(bx, by, ex, ey));
            arr_paths.add(p);
            i = i + 2;
        }
        double firstPointX = geo1.getFirstPoint()[0];
        double firstPointY = geo1.getFirstPoint()[1];
        double lastPointX = geo1.getLastPoint()[0];
        double lastPointY = geo1.getLastPoint()[1];

        ///////////////////////////
        double minlengthF = 0;// 点离开线的距离
        double minlengthL = 0;// 点离开线的距离
        Map<String, Object> tempF = new HashMap<>();
        Map<String, Object> tempL = new HashMap<>();
        for (int i = 0; i < arr_paths.size(); i++) {// 遍历线路数组计算长度
            Map<String, Object> nearF = GetNearestDistance(arr_paths.get(i).get("beginPointX"),
                    arr_paths.get(i).get("beginPointY"), arr_paths.get(i).get("endPointX"),
                    arr_paths.get(i).get("endPointY"), firstPointX, firstPointY);
            Map<String, Object> nearL = GetNearestDistance(arr_paths.get(i).get("beginPointX"),
                    arr_paths.get(i).get("beginPointY"), arr_paths.get(i).get("endPointX"),
                    arr_paths.get(i).get("endPointY"), lastPointX, lastPointY);


            if ((double) nearF.get("length") < minlengthF || i == 0) {// 对比点到线的距离，获取最近的映射点
                minlengthF = (double) nearF.get("length");
                tempF.put("x", nearF.get("x"));
                tempF.put("y", nearF.get("y"));
                tempF.put("index", i);
                tempF.put("shortestDis", minlengthF);
                double disLine = arr_paths.get(i).get("distanceStartPointLength");
                double lengLine = arr_paths.get(i).get("lineLength");
                double disThis = GetPointDistance(arr_paths.get(i).get("beginPointX"), arr_paths.get(i).get("beginPointY"), (double) nearF.get("x"), (double) nearF.get("y"));
                tempF.put("distanceStartPointLength", disLine - lengLine + disThis);
            }

            if ((double) nearL.get("length") < minlengthL || i == 0) {// 对比点到线的距离，获取最近的映射点
                minlengthL = (double) nearL.get("length");
                tempL.put("x", nearL.get("x"));
                tempL.put("y", nearL.get("y"));
                tempL.put("index", i);
                tempL.put("shortestDis", minlengthL);
                double disLine = arr_paths.get(i).get("distanceStartPointLength");
                double lengLine = arr_paths.get(i).get("lineLength");
                double disThis = GetPointDistance(arr_paths.get(i).get("beginPointX"), arr_paths.get(i).get("beginPointY"), (double) nearL.get("x"), (double) nearL.get("y"));
                tempL.put("distanceStartPointLength", disLine - lengLine + disThis);
            }
        }
        Double distanceStartPointLengthF = Double.parseDouble(tempF.get("distanceStartPointLength").toString());
        Double distanceStartPointLengthL = Double.parseDouble(tempL.get("distanceStartPointLength").toString());
        int iF = 0;
        int iL = 0;
        for (int i = 0; i < arr_paths.size(); i++) {// 遍历线路数组计算长度
            double distanceStartPointLength = Double.parseDouble(arr_paths.get(i).get("distanceStartPointLength").toString());
            Double lineLength = Double.parseDouble(arr_paths.get(i).get("lineLength").toString());

            if (distanceStartPointLengthF > distanceStartPointLength - lineLength && distanceStartPointLengthF < distanceStartPointLength) {
                iF = i * 2;
            } else if (distanceStartPointLengthL > distanceStartPointLength - lineLength && distanceStartPointLengthL < distanceStartPointLength) {
                iL = (i + 1) * 2;
            }
        }
        double[] newDataF = Arrays.copyOfRange(geo.getOrdinatesArray(), 0, iF);
        double[] newDataL = Arrays.copyOfRange(geo.getOrdinatesArray(), iL, geo.getOrdinatesArray().length);
        double[] newLinePaths = new double[newDataF.length + geo1.getOrdinatesArray().length + newDataL.length];
        System.arraycopy(newDataF, 0, newLinePaths, 0, newDataF.length);
        System.arraycopy(geo1.getOrdinatesArray(), 0, newLinePaths, newDataF.length, geo1.getOrdinatesArray().length);
        System.arraycopy(newDataL, 0, newLinePaths, newDataF.length + geo1.getOrdinatesArray().length, newDataL.length);
        StringBuffer tempStr = new StringBuffer("");
        tempStr.append("{\"paths\":[[");
        for (int j = 0; j < newLinePaths.length - 1; j++) {
            if (j % 2 == 0) {
                tempStr.append("[");
                tempStr.append(String.valueOf(newLinePaths[j]) + ",");
            } else {
                tempStr.append(String.valueOf(newLinePaths[j]) + "],");
            }
        }
        tempStr.append(String.valueOf(newLinePaths[newLinePaths.length - 1]) + "]]]");
        tempStr.append(",\"spatialReference\":{\"wkid\":4326}}");
        Map result = new HashMap();
        result.put("newLineString", tempStr);
        result.put("newLineJGeo", GeomtryHelper.getJTring2Geom(tempStr.toString()));
        result.put("firstPoint", tempF);
        result.put("lastPoint", tempL);
        return result;
    }

    //最后一个坐标
    public static double[] lastGeometryXY(JGeometry geom) {
        double[] arrpaths = geom.getOrdinatesArray();//获取矢量对象的坐标数组
        double x = arrpaths[arrpaths.length - 2];
        double y = arrpaths[arrpaths.length - 1];
        return new double[]{x, y};
    }

    /**
     * 生成蜂巢
     *
     * @param sideLen                 边长(单位:米)
     * @param min_x,max_x,min_y,max_y 边界坐标
     * @return
     */
    public static List<String> createGrid(float sideLen, double min_x, double max_x, double min_y, double max_y) {
        try {
            ReferencedEnvelope gridBounds = new ReferencedEnvelope(min_x, max_x, min_y, max_y, DefaultGeographicCRS.WGS84);
            SimpleFeatureSource grid = Grids.createHexagonalGrid(gridBounds, sideLen);
            SimpleFeatureCollection resultgrid = grid.getFeatures();
            SimpleFeatureIterator itertorgrid = resultgrid.features();
            List<String> list = new ArrayList<>();
            while (itertorgrid.hasNext()) {
                SimpleFeature feature = itertorgrid.next();
                Polygon polygon = (Polygon) feature.getDefaultGeometry();
                GeometryJSON geometryJson = new GeometryJSON(7);
                StringWriter writer = new StringWriter();
                geometryJson.write(polygon, writer);
                list.add(writer.toString());
                writer.close();
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 判断点是否在面上
     *
     * @param point_x 经度
     * @param point_y 纬度
     * @param polygon 多边形
     * @return
     */
    public static boolean contains(double point_x, double point_y, String polygon) {
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);
        Coordinate coord = new Coordinate(point_x, point_y);
        Point point = geometryFactory.createPoint(coord);
        GeometryJSON json = new GeometryJSON();
        boolean b = false;
        try {
            Polygon polygonObject = json.readPolygon(polygon);
            b = polygonObject.contains(point);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return b;
    }

    public static void main(String[] args) {
        String oldline = "{\"paths\":[[[120.058780427054,30.3115144980066],[120.058310436333,30.3123714209958],[120.058252887275,30.3128363846766],[120.0580487,30.313303],[120.057752536858,30.3144461005454],[120.05741994294,30.3151314761018],[120.0572205,30.3177289000001],[120.056785760741,30.3198522934365],[120.0567806,30.3198775000001],[120.0564643,30.3207762],[120.0561431,30.3216887],[120.0560403,30.3233042000001],[120.0560444,30.3239569000001],[120.0560237,30.3240898000001],[120.0559974,30.324258],[120.0558613,30.3263670000001],[120.055892603267,30.3266421730744],[120.05591,30.3267951000001],[120.0560118,30.3272566000001],[120.0561135,30.3275797],[120.0562546,30.3279045],[120.0564019,30.3281815000001],[120.056684,30.3286291],[120.0569676,30.3289424000001],[120.0574133,30.3293965000001],[120.058849304018,30.3306590384298],[120.0608422,30.3324169000001],[120.0622507,30.3336545999999],[120.06416353278,30.3353471695215]]],\"spatialReference\":{\"wkid\":4326}}";
        String newline = "{\"paths\":[[[120.057593579069,30.3156075092066],[120.0595449,30.3158654000001],[120.059607439548,30.3158748961595],[120.0595449,30.3158654000001],[120.0592697,30.3178400000001],[120.0590014,30.3199794],[120.058964866392,30.3200886542185],[120.0584006,30.3217761000001],[120.0581002,30.3233505000001],[120.0580163,30.3244463000001],[120.0580091,30.3245970999999],[120.0579554,30.3257214000001],[120.0580058,30.3264468000001],[120.058132350171,30.3268746850677],[120.0581989,30.3270997000001],[120.0585154,30.3276507],[120.0588391,30.3280603],[120.058005,30.3284482000001],[120.057514,30.3286474000001],[120.0569676,30.3289424000001],[120.0574133,30.3293965000001],[120.057742078496,30.3296812977127]]],\"spatialReference\":{\"wkid\":4326}}";
        JGeometry geoold = GeomtryHelper.getJTring2Geom(oldline);
        JGeometry geonew = GeomtryHelper.getJTring2Geom(newline);

        buildNewLine(geoold, geonew);

        double leng = GetPointDistance(120.05733487170372, 30.28242984521242, 120.06487724345297, 30.282837499473374);
        GetNearestDistance(120.1009251, 30.2782279000001, 120.105480058215, 30.2783485546391, 120.10466078124522, 30.278326853108073);

        //String s11="{\"paths\":[[[119.391889715,29.2391244660001],[119.395293493,29.2381540600001],[119.396896329,29.237671952],[119.397914292,29.237383053],[119.398631535,29.237162465],[119.39887902,29.2370921240001],[119.398422574,29.235484808],[119.397986379,29.233948732],[119.397922331,29.233723196],[119.397914083,29.2336836380001],[119.399080968,29.2333919120001],[119.401028613,29.2328982760001],[119.403005836,29.2323971070001],[119.40359484,29.232211555],[119.403961506,29.2320727060001],[119.404064851,29.232024042],[119.404282983,29.2319213220001],[119.404341529,29.2318937520001],[119.404927315,29.231529525],[119.406882561,29.230161745],[119.408479492,29.2289146900001],[119.410190385,29.2275516230001],[119.412653103,29.2256362970001],[119.41303001,29.2253536170001],[119.413572634,29.225032265],[119.413515527,29.2248573740001],[119.413399465,29.2241318100001],[119.413293008,29.223322474],[119.413096147,29.222194163],[119.413086852,29.22161142],[119.414626126,29.2215500290001],[119.415546739,29.2214953010001],[119.41617027,29.2214390840001],[119.416483258,29.221415484],[119.417287035,29.221346371],[119.417938598,29.2212947900001],[119.418448758,29.221246632],[119.418937451,29.221205126],[119.419429746,29.2211460190001],[119.420061073,29.2210817910001],[119.420775929,29.2210381370001],[119.421488511,29.2209914900001],[119.42283475,29.220982389],[119.424844313,29.2209808970001],[119.426047562,29.2209912530001],[119.427184746,29.2209468360001],[119.430010852,29.2204993880001],[119.433867958,29.219867245],[119.435864326,29.219542845],[119.43798284,29.2189776440001],[119.439539007,29.2185683770001],[119.440171638,29.218391465],[119.442805463,29.2176977340001],[119.443833431,29.2174236990001],[119.444282157,29.217338554],[119.444775895,29.217189838],[119.445132814,29.217112505],[119.445370761,29.217064916],[119.445781218,29.216987584],[119.446203572,29.2169518910001],[119.446530748,29.2169340450001],[119.446994743,29.2169102510001],[119.447428994,29.2169102510001],[119.447785033,29.2168900510001],[119.44780387,29.215648518],[119.447862425,29.214226265],[119.447865821,29.2141594930001],[119.447894548,29.213594518],[119.448043978,29.213024369],[119.448305718,29.21259904],[119.44871915,29.2121023280001],[119.449630781,29.211038709],[119.450401726,29.210267764],[119.451222641,29.2098251830001],[119.452712104,29.2092998470001],[119.45315151,29.209173735],[119.454174679,29.2088453690001],[119.455069356,29.2084884500001],[119.455348229,29.208469097],[119.455941429,29.2077530380001],[119.456662703,29.2068899880001],[119.457851838,29.2055580850001],[119.458457462,29.2046930440001]]],\"spatialReference\":{\"wkid\":4326}}";
        String s11 = "{\"paths\":[[[120.0842576,30.2771297],[120.0850116,30.2755464000001],[120.0853255,30.2747296000001],[120.0854619,30.2742946000001],[120.0855528,30.2738661],[120.0857083,30.2722692],[120.0859308,30.2701979000001],[120.0860089,30.2698906000001],[120.0860612,30.2695908000001],[120.086228990868,30.2679780393075],[120.0862712,30.2676303000001],[120.0863865,30.266996],[120.0865253,30.2660379000001],[120.086576,30.2656915000001],[120.0866606,30.2651143000001],[120.0866621,30.2649943000001],[120.0866949,30.2648485999999],[120.0868722,30.2648835],[120.08705095717,30.264920362445],[120.092939,30.2661071],[120.0931863,30.2661482],[120.0947284,30.2665006],[120.0953567,30.2666812000001],[120.0960528,30.2669735000001],[120.097014,30.2674153],[120.0971337,30.2675155],[120.097115,30.267651],[120.097075,30.2683539000001],[120.0968532,30.271103],[120.0966253,30.2746215000001],[120.0964947,30.2757193],[120.0960208,30.2780493000001],[120.1009251,30.2782279000001],[120.105480058215,30.2783485546391],[120.1060254,30.2783630000001],[120.1061719,30.2783658],[120.1111097,30.2784357000001],[120.1142438,30.2784674000001],[120.1146809,30.2784709],[120.1150533,30.2784811000001],[120.1150789,30.2776919],[120.1151682,30.2765359000001],[120.1152731,30.2765400000001],[120.1196666,30.2765419],[120.1210778,30.2764442],[120.1218066,30.276413],[120.122754,30.2763984000001],[120.1234756,30.2764692000001],[120.1244515,30.2765977000001],[120.1252552,30.2767208000001],[120.1253782,30.2767333000001],[120.1288528,30.2769118000001],[120.1313932,30.2770644],[120.1315113,30.2770738],[120.1313635,30.2793664],[120.1313477,30.279465],[120.1312429,30.2794602000001],[120.131278094612,30.2789925830535],[120.1313932,30.2770644],[120.1315113,30.2770738],[120.1313635,30.2793664],[120.1313477,30.279465],[120.1311617,30.2816481999999],[120.1311201,30.2823039],[120.1309848,30.2836843000001],[120.130878,30.2853375],[120.1304821,30.2905784000001],[120.130713867232,30.2905861164318],[120.1325073,30.2906487],[120.1331403,30.2907290000001],[120.1335917,30.2907539],[120.1338791,30.2908248000001],[120.1363747,30.2909521000001],[120.1374376,30.2909597],[120.1392394,30.2909910000001],[120.139868401363,30.2910621391659],[120.1398768,30.2911439244405],[120.1392897,30.2910775000001],[120.1374161,30.2910346],[120.1369344,30.2910428000001],[120.1358474,30.2909878],[120.1319241,30.2907779000001],[120.1316272,30.2907630000001],[120.130479236987,30.2907069549168],[120.13031670751,30.2906990200113],[120.124330693092,30.2903675496819],[120.124191491452,30.2903596545108],[120.115912939717,30.2898901156303],[120.114305677048,30.289798955686],[120.114165376469,30.2897909981858],[120.114168179089,30.2897412379489],[120.1141716,30.2896805],[120.114232404311,30.2896838588786],[120.1143128,30.2896883000001],[120.114308885174,30.2897491171708],[120.114305677048,30.289798955686],[120.114165376469,30.2897909981858],[120.1091599,30.2895071000001],[120.109066227386,30.2895021058213],[120.1058419,30.2893302],[120.102986553736,30.2891811646422],[120.102828584032,30.2891737938339],[120.098639392129,30.2889783276829],[120.093945473641,30.2887652487977],[120.093851581287,30.288770542161],[120.093861599443,30.2887347046156],[120.0938694,30.2887068000001],[120.093954,30.2887075],[120.094020798754,30.288709723196],[120.0986292,30.2888631000001],[120.098634381317,30.2889216776699],[120.098639392129,30.2889783276829],[120.0986436,30.2890259000001],[120.0954323,30.2888774],[120.0939355,30.2888328000001],[120.0932472,30.2925990000001],[120.0932125,30.2928647000001],[120.0931973,30.2932507],[120.0932209,30.2945074000001],[120.0932483,30.2957418000001],[120.0932692,30.2970684000001],[120.093269260148,30.2971133904728],[120.093269351362,30.2971816186051],[120.0932694,30.297218],[120.09317680462,30.2972573905751],[120.0930844,30.2972967000001],[120.093084129847,30.2971806499683],[120.093083963709,30.2971092817324],[120.093269260148,30.2971133904728],[120.093269351362,30.2971816186051],[120.0932694,30.297218],[120.0932677,30.299807],[120.0932954,30.3023476000001],[120.0932964,30.3024588],[120.0932928,30.3029955],[120.0931566,30.3040579],[120.0928838,30.305157],[120.0923175,30.3081393],[120.0922683,30.308399],[120.092171376763,30.3089099636378],[120.0921149,30.3092077000001],[120.0920966,30.3093058000001],[120.0916425,30.3116144000001],[120.0912128,30.3137984],[120.0911919,30.313912],[120.0908919,30.3154993000001],[120.0905298,30.3165772],[120.0902736,30.3171961000001],[120.0894074,30.3191610000001],[120.089400955297,30.3192813352226],[120.08939517353,30.3193892921386],[120.0893885,30.3195139],[120.0881751,30.3225985],[120.0873421,30.3245788],[120.0864829,30.3266781],[120.0863034,30.3270847000001],[120.0858665,30.3280439000001],[120.0852716,30.3291649000001],[120.0852013,30.3292536000001],[120.0837729,30.3319193000001],[120.082781721289,30.3340730743934],[120.0827425,30.3341583000001],[120.082581448316,30.3344837610994]]],\"spatialReference\":{\"wkid\":4326}}";
        JGeometry geo11 = GeomtryHelper.getJTring2Geom(s11);
        List<Map> xxxx = GeoToolsHelper.getProjectionPointList(geo11, 120.0981420775132, 30.289002708118513);


        String s0 = "{\"type\":\"polyline\",\"paths\":[[[108.781515696804,34.3010229257316],[108.793589613724,34.2995980392596],[108.807675850129,34.3005479662602],[108.813425334376,34.2976981530288],[108.824636828658,34.2962732101552],[108.836423271365,34.2927107472223],[108.851371930408,34.2922357407507],[108.864308269964,34.2881980773146],[108.893918113837,34.2870104923203]]],\"_path\":0,\"spatialReference\":{\"wkid\":4326},\"cache\":{\"_extent\":{\"xmin\":108.781515696804,\"ymin\":34.2870104923203,\"xmax\":108.893918113837,\"ymax\":34.3010229257316,\"spatialReference\":{\"wkid\":4326}},\"_partwise\":null}}";

        JGeometry geo = GeomtryHelper.getJTring2Geom(s0);
        Map m = GeoToolsHelper.getProjectionPoint(geo, 108.80949741893312, 34.30021570223135);
        List l = GeoToolsHelper.getProjectionPointList(geo, 108.80949741893312, 34.30021570223135);

        String s1 = "{\"type\":\"polyline\",\"paths\":[[[108.781515696804,34.3010229257316],[108.793589613724,34.2995980392596],[108.807675850129,34.3005479662602],[108.813425334376,34.2976981530288],[108.824636828658,34.2962732101552],[108.836423271365,34.2927107472223],[108.851371930408,34.2922357407507],[108.864308269964,34.2881980773146],[108.893918113837,34.2870104923203]]],\"_path\":0,\"spatialReference\":{\"wkid\":4326},\"cache\":{\"_extent\":{\"xmin\":108.781515696804,\"ymin\":34.2870104923203,\"xmax\":108.893918113837,\"ymax\":34.3010229257316,\"spatialReference\":{\"wkid\":4326}},\"_partwise\":null}}";
        String s2 = "{\"paths\":[[[108.78870255211109,34.291760731592994],[108.79172103134087,34.30565363981813],[108.800632731924,34.29461074625206],[108.81198796331216,34.30743461570797],[108.82506803997448,34.283091342760756],[108.85280930146713,34.299479297628594],[108.85625899201544,34.28392269278823],[108.85855878571431,34.28392269278823]]],\"spatialReference\":{\"wkid\":4326},\"type\":\"polyline\"}";
        try {
            GeoToolsHelper.intersectsGeo(s1, s2);
        } catch (ParseException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }


        String s = "{\"paths\":[[[108.60988224609376,34.38540863574218],[108.85570133789064,34.427980657226556],[108.89552677734376,34.540590520507806],[109.05757511718751,34.37167572558593],[109.16331852539064,34.53647064746093],[109.18529118164064,34.37991547167968],[109.31438053710939,34.595522161132806],[109.31300724609376,34.35794281542968]]],\"spatialReference\":{\"wkid\":4326},\"type\":\"polyline\"}";
        String wkt = ArcJson2Wkt(s);
        WKTReader reader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
        try {
            Geometry g1 = reader.read(wkt);
            for (int i = 0; i < 100; i++) {
                //String t=getGetRandomPoints(120.5,30.5,120.5,30.3);
                String t = getGetRandomLine(g1);
                //	System.out.println(t);
            }
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        double[] a = LinearEquationXY(34.3039019188894, 108.915545878179, 34.30379851268016, 108.94189625694995, 2000);
        System.out.println("GetPointDistance:" + GetPointDistance(34.3039019188894, 108.915545878179, 34.303831414655825, 108.93351204552282));
        System.out.println("LinearEquationXY:" + a[0] + "," + a[1]);


    }
}

